﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace Common.Export
{
    public static class SpecSymbols
    {
        public const string NewLine = "&#10;";
    }


    public class StylesList : List<CellStyle>
    {
        public override string ToString()
        {
            string styles = string.Empty;

            styles = "<Styles>" + Environment.NewLine;

            foreach (CellStyle style in this)
                styles += style.ToString() + Environment.NewLine;

            styles += "</Styles>";

            return styles;
        }
    }


    public class ExcelDocument
    {
        private ExcelHeader _header;
        public ExcelHeader Header
        {
            get { return _header; }
            set { _header = value; }
        }

        private StylesList _styles = new StylesList();
        public StylesList Styles
        {
            get { return _styles; }
            set { _styles = value; }
        }

        private List<Worksheet> _worksheets = new List<Worksheet>();
        public List<Worksheet> Worksheets
        {
            get { return _worksheets; }
            set { _worksheets = value; }
        }


        public ExcelDocument()
        {
        }

        public override string ToString()
        {
            string workbook = string.Empty;

            workbook = Header.ToString() + Environment.NewLine;
            workbook += Styles.ToString() + Environment.NewLine;

            foreach (Worksheet sheet in Worksheets)
            {
                workbook += sheet.ToString() + Environment.NewLine;
            }

            workbook += "</Workbook>";

            return workbook;
        }
    }


    public class Table
    {
        private List<Column> _columns = new List<Column>();
        public List<Column> Columns
        {
            get { return _columns; }
            set { _columns = value; }
        }

        private List<Row> _headerRows = new List<Row>();
        public List<Row> HeaderRows
        {
            get { return _headerRows; }
            set { _headerRows = value; }
        }

        private List<Row> _beforeRows = new List<Row>();
        public List<Row> BeforeRows
        {
            get { return _beforeRows; }
            set { _beforeRows = value; }
        }

        private List<Row> _rows = new List<Row>();
        public List<Row> Rows
        {
            get { return _rows; }
            set { _rows = value; }
        }


        public override string ToString()
        {
            string table = string.Empty;

            table = "<Table>";
            foreach (Column col in Columns)
            {
                table += col.ToString() + Environment.NewLine;
            }

            foreach (Row bfrow in BeforeRows)
            {
                table += bfrow.ToString() + Environment.NewLine;
            }

            foreach (Row headrow in HeaderRows)
            {
                table += headrow.ToString() + Environment.NewLine;
            }

            foreach (Row row in Rows)
            {
                table += row.ToString() + Environment.NewLine;
            }

            table += "</Table>";

            return table;
        }
    }


    public class Column
    {
        private int _autoFitWidth = 0;
        public int AutoFitWidth
        {
            get { return _autoFitWidth; }
            set { _autoFitWidth = value; }
        }

        private double _width = 0;
        public double Width
        {
            get { return _width; }
            set { _width = value; }
        }

        private int _index = 1;
        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }


        public override string ToString()
        {
            string column = string.Empty;
            column = string.Format("<Column ss:AutoFitWidth=\"{0}\" ss:Width=\"{1}\" ss:Index=\"{2}\"/>", AutoFitWidth, Width.ToString().Replace(",", "."), Index);

            return column;
        }
    }


    public class Row
    {
        private int _autoFitHeight = 1;
        public int AutoFitHeight
        {
            get { return _autoFitHeight; }
            set { _autoFitHeight = value; }
        }

        private double _height;
        public double Height
        {
            get { return _height; }
            set { _height = value; }
        }

        private List<Cell> _cells = new List<Cell>();
        public List<Cell> Cells
        {
            get { return _cells; }
            set { _cells = value; }
        }


        public override string ToString()
        {
            string headerRow = string.Empty;

            headerRow = string.Format("<Row ss:AutoFitHeight=\"{0}\" ", AutoFitHeight);
            if (Height != null && Height > 0)
                headerRow += string.Format(" ss:Height=\"{0}\" ", Height.ToString().Replace(",", "."));
            headerRow += ">" + Environment.NewLine;

            foreach (Cell cell in Cells)
                headerRow += cell.ToString() + Environment.NewLine;

            headerRow += "</Row>";

            return headerRow;
        }
    }


    public class Cell
    {
        private string _styleID;
        public string StyleID
        {
            get { return _styleID; }
            set { _styleID = value; }
        }

        private string _type = "String";
        public string Type
        {
            get { return _type; }
            set { _type = value; }
        }

        private string _data;
        public string Data
        {
            get { return _data; }
            set { _data = value; }
        }

        private int _mergeAcross;
        public int MergeAcross
        {
            get { return _mergeAcross; }
            set { _mergeAcross = value; }
        }

        private int _mergeDown;
        public int MergeDown
        {
            get { return _mergeDown; }
            set { _mergeDown = value; }
        }

        private int _index;
        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }


        public override string ToString()
        {
            string cell = string.Empty;

            cell = "<Cell";
            if (StyleID != null && StyleID.Length > 0)
                cell += string.Format(" ss:StyleID=\"{0}\" ", StyleID);
            if (MergeAcross != null && MergeAcross > 0)
                cell += string.Format(" ss:MergeAcross=\"{0}\" ", MergeAcross);
            if (MergeDown != null && MergeDown > 0)
                cell += string.Format(" ss:MergeDown=\"{0}\" ", MergeDown);
            if (Index != null && Index > 0)
                cell += string.Format(" ss:Index=\"{0}\" ", Index);
            cell += ">";

            if (Data != null && Data.Length > 0)
                cell += string.Format("<ss:Data ss:Type=\"{0}\" xmlns=\"http://www.w3.org/TR/REC-html40\">{1}</ss:Data>", Type, Data);

            cell += "</Cell>";

            return cell;
        }
    }


    public class Worksheet
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private Table _table;
        public Table Table
        {
            get { return _table; }
            set { _table = value; }
        }

        public override string ToString()
        {
            string worksheet = string.Empty;

            worksheet = string.Format("<Worksheet ss:Name=\"{0}\">", Name) + Environment.NewLine;
            worksheet += Table.ToString() + Environment.NewLine;
            worksheet += "</Worksheet>";

            return worksheet;
        }
    }


    public class CellStyle
    {
        public string ID = string.Empty;

        public Thickness Borders = new Thickness(0.0);
        public HorizontalAlignment HorizontalAlignment = HorizontalAlignment.Left;
        public VerticalAlignment VerticalAlignment = VerticalAlignment.Top;
        public TextWrapping TextWrapping = TextWrapping.Wrap;
        public FontWeight FontWeight = FontWeights.Normal;
        public FontStyle FontStyle = FontStyles.Normal;
        public int FontSize = 11;
        public Color? FontColor = null;
        public FontFamily FontFamily = new FontFamily("Calibri");
        public Color? InteriorColor = null;
        public int StrikeThrough;
        public string NumberFormat = "";

        public override string ToString()
        {
            string style = string.Empty;
            int isWrap = (this.TextWrapping == TextWrapping.Wrap) ? 1 : 0;

            style =
                string.Format("<Style ss:ID=\"{0}\">", ID) + Environment.NewLine +
                string.Format("<Alignment ss:Horizontal=\"{0}\" ss:Vertical=\"{1}\" ss:WrapText=\"{2}\"/>", HorizontalAlignment.ToString(), VerticalAlignment.ToString(), isWrap.ToString()) + Environment.NewLine +
                ((Borders != null && (Borders.Bottom > 0 || Borders.Left > 0 || Borders.Right > 0 || Borders.Top > 0)) ?
                    ("<Borders>" + Environment.NewLine +
                    ((Borders.Bottom > 0) ? (string.Format("<Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"{0}\"/>", Borders.Bottom.ToString().Replace(",", ".")) + Environment.NewLine) : "") +
                    ((Borders.Left > 0) ? (string.Format("<Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"{0}\"/>", Borders.Left.ToString().Replace(",", ".")) + Environment.NewLine) : "") +
                    ((Borders.Right > 0) ? (string.Format("<Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"{0}\"/>", Borders.Right.ToString().Replace(",", ".")) + Environment.NewLine) : "") +
                    ((Borders.Top > 0) ? (string.Format("<Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"{0}\"/>", Borders.Top.ToString().Replace(",", ".")) + Environment.NewLine) : "") +
                    "</Borders>" + Environment.NewLine)
                    : "") +
                string.Format("<Font ss:FontName=\"{0}\" ss:Size=\"{1}\" ", FontFamily.Source, FontSize.ToString());

            if (FontColor != null)
                style += string.Format(" ss:Color=\"{0}\" ", FontColor.ToString().Remove(1, 2));

            if (StrikeThrough != null && StrikeThrough > 0)
                style += string.Format(" ss:StrikeThrough=\"{0}\" ", StrikeThrough.ToString());

            if (FontWeight != FontWeights.Normal)
                style += "ss:Bold=\"1\" ";

            if (FontStyle == FontStyles.Italic)
                style += " ss:Italic=\"1\" ";

            style += "/>" + Environment.NewLine;

            if (InteriorColor != null)
                style += string.Format("<Interior ss:Color=\"{0}\" ss:Pattern=\"Solid\"/>", InteriorColor.ToString().Remove(1, 2)) + Environment.NewLine;

            //style += "<NumberFormat />" + Environment.NewLine +
            style += ("<NumberFormat " + (!string.IsNullOrEmpty(NumberFormat) ? string.Format("ss:Format=\"{0}\"", NumberFormat) : "") + " />" + Environment.NewLine +
                "<Protection/>" + Environment.NewLine +
                "</Style>");

            return style;
        }
    }


    public class ExcelHeader
    {
        private DocumentProperties _documentProperties;
        public DocumentProperties DocumentProperties { get; set; }

        private WindowProperties _windowProperties;
        public WindowProperties WindowProperties { get; set; }

        public ExcelHeader()
        {
            DocumentProperties = new DocumentProperties();
            WindowProperties = new WindowProperties();
        }

        public override string ToString()
        {
            string header;

            header =
                "<?xml version=\"1.0\"?>" + Environment.NewLine +
                "<?mso-application progid=\"Excel.Sheet\"?>" + Environment.NewLine +
                "<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"" + Environment.NewLine +
                "xmlns:o=\"urn:schemas-microsoft-com:office:office\"" + Environment.NewLine +
                "xmlns:x=\"urn:schemas-microsoft-com:office:excel\"" + Environment.NewLine +
                "xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"" + Environment.NewLine +
                "xmlns:html=\"http://www.w3.org/TR/REC-html40\">" + Environment.NewLine;

            if (DocumentProperties != null)
            {
                header +=
                    "<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">" + Environment.NewLine +
                    string.Format("<Author>{0}</Author>", DocumentProperties.Author) + Environment.NewLine +
                    string.Format("<LastAuthor>{0}</LastAuthor>", DocumentProperties.LastAuthor) + Environment.NewLine +
                    string.Format("<Created>{0}</Created>", DocumentProperties.Created.ToString()) + Environment.NewLine +
                    string.Format("<Company>{0}</Company>", DocumentProperties.Company) + Environment.NewLine +
                    string.Format("<Version>{0}</Version>", DocumentProperties.Version.ToString()) + Environment.NewLine +
                    "</DocumentProperties>" + Environment.NewLine;
            }

            header += "<ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">" + Environment.NewLine;

            if (WindowProperties != null)
            {
                header +=
                    string.Format("<WindowHeight>{0}</WindowHeight>", WindowProperties.WindowHeight.ToString()) + Environment.NewLine +
                    string.Format("<WindowWidth>{0}</WindowWidth>", WindowProperties.WindowWidth.ToString()) + Environment.NewLine +
                    string.Format("<WindowTopX>{0}</WindowTopX>", WindowProperties.WindowTopX.ToString()) + Environment.NewLine +
                    string.Format("<WindowTopY>{0}</WindowTopY>", WindowProperties.WindowTopY.ToString()) + Environment.NewLine +
                    string.Format("<ProtectStructure>{0}</ProtectStructure>", WindowProperties.ProtectStructure.ToString()) + Environment.NewLine +
                    string.Format("<ProtectWindows>{0}</ProtectWindows>", WindowProperties.ProtectWindows.ToString()) + Environment.NewLine;
            }

            header += "</ExcelWorkbook>";

            return header;
        }
    }


    public class DocumentProperties
    {
        private string _author = string.Empty;
        public string Author
        {
            get { return _author; }
            set { _author = value; }
        }

        private string _lastAuthor = string.Empty;
        public string LastAuthor
        {
            get { return _lastAuthor; }
            set { _lastAuthor = value; }
        }

        private DateTime _created = DateTime.Now;
        public DateTime Created
        {
            get { return _created; }
            set { _created = value; }
        }

        private string _company = string.Empty;
        public string Company
        {
            get { return _company; }
            set { _company = value; }
        }

        private double _version = 1.0;
        public double Version
        {
            get { return _version; }
            set { _version = value; }
        }
    }


    public class WindowProperties
    {
        private int _windowHeight = 0;
        public int WindowHeight
        {
            get { return _windowHeight; }
            set { _windowHeight = value; }
        }

        private int _windowWidth = 0;
        public int WindowWidth
        {
            get { return _windowWidth; }
            set { _windowWidth = value; }
        }

        private int _windowTopX = 0;
        public int WindowTopX
        {
            get { return _windowTopX; }
            set { _windowTopX = value; }
        }

        private int _windowTopY = 0;
        public int WindowTopY
        {
            get { return _windowTopY; }
            set { _windowTopY = value; }
        }

        private bool _protectStructure = false;
        public bool ProtectStructure
        {
            get { return _protectStructure; }
            set { _protectStructure = value; }
        }

        private bool _protectWindows = false;
        public bool ProtectWindows
        {
            get { return _protectWindows; }
            set { _protectWindows = value; }
        }
    }
}
